import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
import java.awt.Toolkit;

import java.awt.event.*;
import java.util.*;

import java.lang.Object;
import java.lang.Class;

public class Game
{
	char[] gameType;
	
	Board board;
	
	Board lastBoard;
	Board undoBoard;
	boolean canUndo;
	
	boolean help;
	boolean ptLose;
	
	Player pOne;	
	Player pTwo;
	
		
	int turn;
	boolean gameOver;
	
	int inValidTurns;	
	
	Butt pass;	
	Butt restart;
	Butt undo;
	Butt quit;
	
	Pic pOneBackG;
	Pic pTwoBackG;
	Pic winnerPic;
	
	Main root;
			
	public Game(char[] gT, Main r)
	{		
		switch(gT[3])//Board Size
		{
			case 's':	board = new Board(6,1);
						break;
						
			case 'm':	board = new Board(8,1);
						break;
						
			case 'l':	board = new Board(12,1);
						break;
						
			case 't':	board = new Board(16,1);
						break;
						
			case 'S':	board = new Board(6,6);
						break;
						
			case 'M':	board = new Board(8,8);
						break;
						
			case 'L':	board = new Board(12,12);
						break;
						
			case 'T':	board = new Board(16,16);
						break;
						
			default	:	break;		
		}
		switch(gT[0])//Players
		{
			case 'p':	pOne = new Player(0, gT[1]);
						pTwo = new Player(1, gT[2]);
						break;
						
			case 'v':	pOne = new Player(0, gT[1]);
						pTwo = getAI(gT[2], board.size, board.zSize, 1);
						break;
						
			case 'c':	pOne = getAI(gT[1], board.size, board.zSize, 0);
						pTwo = getAI(gT[2], board.size, board.zSize, 1);
						break;
						
			default	:	break;
		}	
		
		root = r;
		
		help = false;
		if(gT[4] == 'y')
			help = true;
			
		ptLose = false;
		if(gT[5] == 'y')
			ptLose = true;
		
		gameType = gT;
		turn = 1;
		gameOver = false;
		inValidTurns = 0;
		
		help();		
		
		undoBoard = new Board(board);
		lastBoard = new Board(board);
		canUndo = false;
		
		pass = new Butt(204, 482, 196, 53, "passButt.jpg");
		restart = new Butt(204, 482, 196, 53, "restartButt.jpg");
		undo = new Butt(449, 489, 129, 53, "undoButt.jpg");
		quit = new Butt(360, 539, 180, 56, "quitGameButt.jpg");
		
		pOneBackG = new Pic("Game\\greenBox.gif", 0, 0);
		pTwoBackG = new Pic("Game\\blueBox.gif", 650, 0);
			
	}
	
	public Player getAI(char personal, int s, int z, int p)
	{
		if(z == 1)
		{
			switch(personal)
			{
				case 'm':	return new MayoPlayer(s, p);
							
				case 'h':	return new HotDogPlayer(s, p);
							
				case 'f':	return new FlowerPlayer(s, p);
				
				case 'b': 	return new BetterPlayer(s, p);
							
			}
		}
		else
		{
			switch(personal)
			{
				case 'M':	return new MayoPlayer3D(s, p);

				//case 'H':	return new HotDogPlayer3D(s, p);

				//case 'F':	return new FlowerPlayer3D(s, p);
				
				case 'B':	return new BetterPlayer3D(s,p);

			}
		}
		return new MayoPlayer(s, p);
		
	}
	
	public Pic[] getPics()
	{
		Pic[] pics = new Pic[8];
				
		pics[0] = pass.getPic();
		pics[1] = restart.getPic();
		pics[2] = undo.getPic();
		pics[3] = quit.getPic();
		pics[4] = pOneBackG;
		pics[5] = pTwoBackG;
		pics[6] = pOne.image;
		pics[7] = pTwo.image;
					
		return pics;		
	}	
	
		
	public void mouseMove(int mX, int mY)
	{
		//pass.mouseMove(mX, mY);
		restart.mouseMove(mX,mY);
		undo.mouseMove(mX,mY);
		quit.mouseMove(mX,mY);
	}
	
	public void click(int mX, int mY)
	{
		//System.out.println("click- game");
		if(restart.isIn(mX,mY))
		{
			//restartGame();		
		}
			
		else if(undo.isIn(mX,mY) && (gameType[0] == 'p' || (gameType[0] == 'c' && turn == 1)))
		{
			//undo();
		}
		
		//else if(pass.isIn(mX,mY) && (gameType[0] == 'p' || (gameType[0] == 'c' && turn == 1)))
		//{
		//	pass();
		//}
		else if(quit.isIn(mX,mY))
		{
			System.exit(0);
		}			
	}
	
	public void piecesCount()
	{
		pOne.pieces = board.count(1);
		pTwo.pieces = board.count(2);
		
		System.out.println("Green: "+pOne.pieces+" Blue: "+pTwo.pieces);
	}
	
	public void gameDone()
	{
		System.out.println("Game Over!");
		piecesCount();
		if(!ptLose)
		{
			if(pOne.pieces > pTwo.pieces)
			{	
				//winnerPic.name = pOne.image;
				System.out.println("Green Wins!");
			}
			else if(pTwo.pieces > pOne.pieces)
			{	
				System.out.println("Blue Wins!");
				//winnerPic.name = pTwo.image;
			}
			else
			{	
				System.out.println("Tie!");
			}
		}
		else
		{
			if(pOne.pieces < pTwo.pieces)
			{	
				//winnerPic.name = pOne.image;
				System.out.println("Green Wins!");
			}
			else if(pTwo.pieces < pOne.pieces)
			{	
				System.out.println("Blue Wins!");
				//winnerPic.name = pTwo.image;
			}
			else
			{	
				System.out.println("Tie!");
			}
		}
	}
	
	public void changeTurn()
	{
		if(turn == 1)
			turn = 2;			
		else
			turn = 1;
			
		help();
	}
	
	public void help()
	{
		if(help)
		{
			board.clearMarks();
			board.markMoves(turn);
		}
	}
	
	public void restartGame()
	{
		switch(gameType[3])//Board Size
		{
			case 's':	board = new Board(6,1);
						break;
						
			case 'm':	board = new Board(8,1);
						break;
						
			case 'l':	board = new Board(12,1);
						break;
						
			case 't':	board = new Board(16,1);
						break;
						
			case 'S':	board = new Board(6,6);
						break;
						
			case 'M':	board = new Board(8,8);
						break;
						
			case 'L':	board = new Board(12,12);
						break;
						
			case 'T':	board = new Board(16,16);
						break;
						
			default	:	break;		
		}
		switch(gameType[0])//Players
		{
			case 'p':	pOne = new Player(1, gameType[1]);
						pTwo = new Player(2, gameType[2]);
						break;
						
			case 'v':	pOne = new Player(1, gameType[1]);
						pTwo = getAI(gameType[2], board.size, board.zSize, 1);
						break;
						
			case 'c':	pOne = getAI(gameType[1], board.size, board.zSize, 0);
						pTwo = getAI(gameType[2], board.size, board.zSize, 1);
						break;
						
			default	:	break;
		}
		
		help = false;
		if(gameType[4] == 'y')
			help = true;
		
		ptLose = false;
		if(gameType[5] == 'y')
			ptLose = true;
		
		turn = 1;
		gameOver = false;
		inValidTurns = 0;
		
		help();	
		
		undoBoard = new Board(board);
		lastBoard = new Board(board);
		canUndo = false;
		
		//!!!!!!!!
		//pass = new Butt(204, 482, 196, 53, "passButt.jpg");
		//!!!!!!!!!
		restart = new Butt(204, 482, 196, 53, "restartButt.jpg");
		undo = new Butt(449, 489, 129, 53, "undoButt.jpg");
		quit = new Butt(360, 539, 180, 56, "quitGameButt.jpg");
	}
	
	public void undo()
	{
		if(canUndo)
		{			
			board = new Board(undoBoard);
			undoBoard = new Board(lastBoard);
			lastBoard = new Board(board);
			
			changeTurn();
			
			canUndo = false;
			piecesCount();
			gameOver = false;				
		}
	}
	
	public void pass()
	{
		inValidTurns++;
			
		undoBoard = new Board(lastBoard);
		lastBoard = new Board(board);
		canUndo = true;
		
		System.out.println("pass");
		
		changeTurn();			
	}
	
	public void attemptMove(int[] cords)
	{
		if(!gameOver)
		{
			char p;
			if(turn == 1)
				p = 'g';
			else
				p = 'b';
			
			if(board.makeMove(cords[0], cords[1], cords[2], p))
			{
				changeTurn();
									
				undoBoard = new Board(lastBoard);
				lastBoard = new Board(board);
				canUndo = true;
				
				inValidTurns = 0;
				
				checkEndGame();		
				
				if(gameType[0] == 'v')
				{
					AITurn();
				}
				
			}
		}
	}
	
	public void AITurn()
	{		
		if(!gameOver)
		{					
			char p;
			if(turn == 1)
				p = 'g';
			else
				p = 'b';
				
			if(turn == 1 && board.zSize == 1)
			{
				int[] newMove = new int[2];
				
				//AI call
				if(!ptLose)								
					pOne.makeMove(board.size, board.getState2D(), board.lastMove2D(), new Long(0), newMove);
				else
					pOne.makeBadMove(board.size, board.getState2D(), board.lastMove2D(), new Long(0), newMove);
				
				if(newMove[0] == -1 || newMove[1] == -1)
				{
					pass();
				}
				else
				{
					board.makeMove(newMove[0], newMove[1], 0, p);
					
					undoBoard = new Board(lastBoard);
					lastBoard = new Board(board);
					canUndo = true;
					
					changeTurn();
															
					inValidTurns = 0;
				}
				checkEndGame();					
				
			}
			else if(turn == 2 && board.zSize == 1)
			{
				int[] newMove = new int[2];
				
				//AI call								
				if(!ptLose)								
					pTwo.makeMove(board.size, board.getState2D(), board.lastMove2D(), new Long(0), newMove);
				else
					pTwo.makeBadMove(board.size, board.getState2D(), board.lastMove2D(), new Long(0), newMove);
				
				if(newMove[0] == -1 || newMove[1] == -1)
				{
					pass();
				}
				else
				{
					board.makeMove(newMove[0], newMove[1], 0, p);
					undoBoard = new Board(lastBoard);
					lastBoard = new Board(board);
					canUndo = true;
					
					changeTurn();
										
					inValidTurns = 0;
				}
				checkEndGame();					
				
			}			
			else if(turn == 1)
			{
				int[] newMove = new int[3];
				
				//AI call
				if(!ptLose)								
					pOne.makeMove3D(board.size, board.getState(), board.lastMove, new Long(0), newMove);
				else
					pOne.makeBadMove3D(board.size, board.getState(), board.lastMove, new Long(0), newMove);
				
				if(newMove[0] == -1 || newMove[1] == -1)
				{
					pass();
				}
				else
				{
					board.makeMove(newMove[0], newMove[1], newMove[2], p);
					undoBoard = new Board(lastBoard);
					lastBoard = new Board(board);
					canUndo = true;
					
					changeTurn();
																			
					inValidTurns = 0;
				}
				checkEndGame();					
			}
			else if(turn == 2)
			{
				System.out.println("ai moving");
				int[] newMove = new int[3];
				
				//AI call							
				if(!ptLose)
					pTwo.makeMove3D(board.size, board.getState(), board.lastMove, new Long(0), newMove);
				else
					pTwo.makeBadMove3D(board.size, board.getState(), board.lastMove, new Long(0), newMove);					
				
				if(newMove[0] == -1 || newMove[1] == -1)
				{
					pass();
				}
				else
				{
					System.out.println("ai got move "+newMove[0]+" "+newMove[1]+" "+newMove[2]);
					board.makeMove(newMove[0], newMove[1], newMove[2], p);
					undoBoard = new Board(lastBoard);
					lastBoard = new Board(board);
					canUndo = true;
					
					changeTurn();
														
					inValidTurns = 0;
				}
				checkEndGame();			
			}
			
			root.updateSpheres();
			
			if(gameType[0] == 'c')
				AITurn();			
		}
	}
	
	public void checkEndGame()
	{
		if(board.isFull())
			gameOver = true;
		
		if(inValidTurns >= 3)
			gameOver = true;
		
		if(gameOver)
			gameDone();
	}
}